#===============================================================================
# Koro Business Environment
# Copyright (C) 2008  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================
#Controller.
print 'importo controller'

#import socket
#import sys
import koro
from koro.core import interface
from koro.core import context,exception
from koro.db import database
from koro.ui import view


#===============================================================================
# Controller
#===============================================================================
class Controller(interface.Observer):
    def __init__(self):
        view.get_instance().init(self)#mostra splashscreen
        self.__context=None
        self.__options=None
        self.__configuration=koro.Configuration()
        self.__transaction=False
    
    def __getattribute__(self,name):
        error=None
        try:
            return object.__getattribute__(self,name)
        except AttributeError,e:
            error=e
        try:
            return object.__getattribute__(self.__context,name)
        except:
            raise AttributeError(error)
    
    def check_module(self,name):
        try:
            __import__('koro.modules.{0}'.format(name))
        except ImportError:
            return False
        return True
             
                
    def __get_options(self):
        self.set_opzioni_context()
        return self.get_objects()
    
    def get_option(self,opt):
        return self.get_options().__getattribute__(opt)
    
    def get_options(self):
        if self.__options.is_dirty():
            self.__options=self.__get_options()
        return self.__options

    def run(self):
        self.configure()
        view.get_instance().main_loop()
    
    def configure(self):        
        self.__configuration.configure()       
        database.get_instance().configure(self.__configuration)
        self.__options=self.__get_options()#deve stare obbligatoriamente dopo la configurazione del db
        view.get_instance().configure(self,self.__configuration)
           
    def set_context(self,context_):
        #assert issubclass(context_,context.Context),Exception('%s:Atteso tipo Context' % self.__class__.__name__)
        del self.__context
        try:
            context_=self.__configuration.to_context(context_)
            self.__context=context_()
        except TypeError:
            raise exception.KoroContextError('{0}: contesto non valido.'.format(context_)) 
    
#    def set_ordini_fornitore_context(self):        
#        return self.set_context(context.OrdiniFornitoreContext)
#    
#    def set_ordini_cliente_context(self):        
#        return self.set_context(context.OrdiniClienteContext)
#        
#    def set_vendite_banco_context(self):
#        return self.set_context(context.VenditaBancoContext)
    
    def set_opzioni_context(self):
        return self.set_context(context.OpzioniContext)    
    
    #def get_object_class(self):
    #    return self.__context.get_object_class()

    #def get_objects(self,*args,**kwargs):        
    #    return self.__context.get_objects(*args,**kwargs)
    
    #def get_object(self,*args,**kwargs):        
    #    return self.__context.get_object(*args,**kwargs)
    
    def process_request(self,context_ID):
        '''Questo metodo viene invocato quando l'utente richiede un'azione da menu. '''
        context_=self.__configuration[context_ID]
        self.request_view(context_)

    def request_view(self,context_):
        try:
#            database.get_instance().clear()#in teoria quando apro una pagina posso pulire la sessione
            self.set_context(context_)
            objects=self.get_objects()
            page,args,kwargs=self.__configuration[context_]            
            view.get_instance().request_view(page,objects,context_,*args,**kwargs)
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            database.get_instance().rollback()
    
#    def notify_page_closing(self):
#        database.get_instance().clear()
    
    def request_action(self,context_,action,*args,**kwargs):
        try:
            self.set_context(context_)
            response=self.__context.__getattribute__(action)(*args,**kwargs)
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            database.get_instance().rollback()
            raise Exception(e)
        return response

    def save_object(self,obj):
        try:
            self.__context.save_object(obj)
        except exception.KoroInvalidObject,inst:
            view.get_instance().show_error(inst)
            #TODO:con i nuovi documenti su errore in obj.validate() fa rollback su add documento,
            # quindi rimuove l'oggetto dalla sessione e un eventuale expunge va in errore.
            #che succede con altri oggetti????(prodotti,anagrafiche,listini,ecc)
            #database.get_instance().rollback()#problema: fa rollback su add documento!!!!
            raise Exception(inst)
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            database.get_instance().rollback()
            raise Exception(e)
    
    def save_data(self,context_,data):
        current_context=self.__context.__class__
        self.set_context(context_)
        self.save_object(data)
        self.set_context(current_context)

    def delete_object(self,obj):
        try:
            self.__context.delete_object(obj)
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            database.get_instance().rollback()
            raise Exception(e)

    def new_object(self):
        try:
            new_object=self.__context.new_object()
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            new_object=None
            database.get_instance().rollback()
            raise Exception(e)
        return new_object

    def update_object(self,obj):
        self.save_object(obj)
    
    def action_request(self,action,*args,**kwargs):
        try:
            response=self.__context.__getattribute__(action)(*args,**kwargs)
        except Exception,e:
            print e
            view.get_instance().show_error(e)
            database.get_instance().rollback()
            raise Exception(e)
        return response
    
    def begin_transaction(self):
        self.__transaction=True
    
    def commit(self):
        if not self.__transaction:
            view.get_instance().show_error('Nessuna transazione attiva.')
            return
        self.__transaction=False
        try:
            database.get_instance().commit()
        except Exception,e:
            print e
            database.get_instance().rollback()
            view.get_instance().show_error(e)
    
    def flush(self):
        try:
            database.get_instance().flush()
        except Exception,e:
            print e
            database.get_instance().rollback()
            view.get_instance().show_error(e)
    
    def notify_closing(self):
        print 'richiesta di chiusura sessione database'
        database.get_instance().close()
    
    
        
